package com.ebt.m.customer.view;

/**
 * Created by Rick.Wang on 2016/5/5.
 */

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;

import com.ebt.m.R;
import com.ebt.m.customer.util.DisplayUtil;

/**
 * Created by Rick.Wang on 2016/5/5.
 */
public class RecorderView extends LinearLayout implements View.OnTouchListener{

    private static final int DEFAULT_ROUND_RECT_REDIUS_DP = 4;
    public static final int THRESHOLD_RECORD_SPAN = 1000;//最短录制1000毫秒

    public static final int CANCEL_TIME_SHORT = 0;
    public static final int CANCEL_MANUALLY = 1;
    public static final int CANCEL_OTHER = 2;

    private static final int THRESHOLD_DISTANCE_DP = 100;
    private static final int TEXT_SIZE_SP = 20;

    private float curRawY;
    private float orgRawY;
    private boolean flagPressed = false;
    private int colorBgPressed = 0xffcfcfcf;
    private int colorBgNormal = 0xffefefef;
    private int colorStrokePressed = 0xffeeeeee;
    private int colorStrokeNormal = 0xffeeeeee;
//    private int colorStrokePressed = 0xff9a9a9a;
//    private int colorStrokeNormal = 0xffbababa;

    private int colorBgCurr = 0;
    private int colorStrokeCurr = 0;
    private int mRoundRectRedius = -1;

    private int mThresholdDistancePx = 0;

    private enum State{
        IDLE, RECODING, CANCEL_TRIGGERED
    }

    private State state = State.IDLE;

    private Paint mPaint = new Paint();

    public RecorderView(Context context) {
        super(context);
        init();
    }

    public RecorderView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttr(context, attrs);
        init();
    }

    public RecorderView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttr(context, attrs);
        init();
    }

    private void init(){
        if(mRoundRectRedius < 0){
            mRoundRectRedius = DisplayUtil.dip2px(getContext(), DEFAULT_ROUND_RECT_REDIUS_DP);
        }
        this.setOnTouchListener(this);
        mThresholdDistancePx = dp2px(getContext(), THRESHOLD_DISTANCE_DP);
        mPaint.setColor(0xff000000);
        mPaint.setDither(true);
        mPaint.setAntiAlias(true);
        mPaint.setTextSize(sp2px(getContext(), TEXT_SIZE_SP));
        mPaint.setTextAlign(Align.CENTER);
    }

    private void initAttr(Context context, AttributeSet attrs){
        if (attrs == null) {
            return;
        }
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RecorderView);
        int n = a.getIndexCount();
        for (int i = 0; i < n; i++) {
            int attr = a.getIndex(i);
            if(attr == R.styleable.RecorderView_rv_Text){
            } else if(attr == R.styleable.RecorderView_rv_RoundRectRedius){
                mRoundRectRedius = a.getDimensionPixelSize(attr, DisplayUtil.dip2px(getContext(), DEFAULT_ROUND_RECT_REDIUS_DP));
            }
        }
        a.recycle();
    }

    private RectF mRectF = new RectF();
    private RectF mRectFStroke = new RectF();
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mRectF.left = 0;
        mRectF.top = 0;
        mRectF.right = w;
        mRectF.bottom = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawBg(canvas);
    }

    private void drawBg(Canvas canvas){
        if(flagPressed){
            colorBgCurr = colorBgPressed;
            colorStrokeCurr = colorStrokePressed;
        }else{
            colorBgCurr = colorBgNormal;
            colorStrokeCurr = colorStrokeNormal;
        }

        mPaint.setColor(colorBgCurr);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawRoundRect(mRectF, mRoundRectRedius, mRoundRectRedius, mPaint);

        mPaint.setColor(colorStrokeCurr);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(2);
        mRectFStroke.left = mRectF.left + 1;
        mRectFStroke.top = mRectF.top + 1;
        mRectFStroke.right = mRectF.right - 1;
        mRectFStroke.bottom = mRectF.bottom - 1;
        canvas.drawRoundRect(mRectFStroke, mRoundRectRedius, mRoundRectRedius, mPaint);
    }

    private OnRecoderClickListener mOnRecoderClickListener;
    public void setOnRecoderClickListener(OnRecoderClickListener listener){
        mOnRecoderClickListener = listener;
    }

    public interface OnRecoderClickListener{
        boolean onRecoderStart(String simpleFileName);
        boolean onRecoderCancel(String simpleFileName, int reason);
        boolean onRecoderFinish(String simpleFileName);
        void onRecoderCancelTriggerd(String simpleFileName);
        void onRecoderCancelDismissed(String simpleFileName);
    }

    private long startTime;
    private String fileName;

    private void analyzeMotion(float orgRawY, float curRawY){
        if(orgRawY - curRawY > mThresholdDistancePx){
            if(state == State.RECODING){
                state = State.CANCEL_TRIGGERED;
                if(mOnRecoderClickListener != null){
                    mOnRecoderClickListener.onRecoderCancelTriggerd(fileName);
                }
            }
        }else{
            if(state == State.CANCEL_TRIGGERED){
                state = State.RECODING;
                if(mOnRecoderClickListener != null){
                    mOnRecoderClickListener.onRecoderCancelDismissed(fileName);
                }
            }
        }
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                flagPressed = true;
                if(mOnRecoderClickListener != null){
                    fileName = RecorderWrapper.generateSimpleFileName();
                    if(mOnRecoderClickListener.onRecoderStart(fileName)) {
                        state = State.RECODING;
                        orgRawY = curRawY = event.getRawY();
                        startTime = System.currentTimeMillis();
                    }
                }
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                flagPressed = true;
                curRawY = event.getRawY();
                analyzeMotion(orgRawY, curRawY);
                break;
            case MotionEvent.ACTION_UP:
                flagPressed = false;
                if(mOnRecoderClickListener != null){
                    switch (state){
                        case RECODING:
                            if(System.currentTimeMillis() - startTime > THRESHOLD_RECORD_SPAN){
                                if(mOnRecoderClickListener.onRecoderFinish(fileName)){
                                    state = State.IDLE;
                                }
                            }else{
                                mOnRecoderClickListener.onRecoderCancel(fileName, CANCEL_TIME_SHORT);
                                state = State.IDLE;
                            }
                            break;
                        case CANCEL_TRIGGERED:
                            if(mOnRecoderClickListener.onRecoderCancel(fileName, CANCEL_MANUALLY)){
                                state = State.IDLE;
                            }
                            break;
                    }
                }
                startTime = 0;
                invalidate();
                break;
            case MotionEvent.ACTION_CANCEL:
                flagPressed = false;
                if(mOnRecoderClickListener != null){
                    if(mOnRecoderClickListener.onRecoderCancel(fileName, CANCEL_OTHER)){
                        state = State.IDLE;
                    }
                }
                invalidate();
                break;
        }
        return true;
    }

    private int sp2px(Context context, float spValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

    private int dp2px(Context context, float dpValue) {
        final float densityScale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * densityScale + 0.5f);
    }
}